package com.young.design.pattern.singleton;

/**
 * @ClassName : SingleTon4
 * @Author : hyy
 * @Date: 2020-03-14
 * 懒汉式 单例模式 ----线程安全的写法，改进（任然有缺陷）
 * 双端检查,,先进行检查，判断单例对象是否为空，如果为空，加锁进行创建
 * 为避免在一个线程判断单例对象为空后，其他线程介入，创建单例对象，
 * 所以在创建对象钱再进行一次判断单例对象是否为空，如果为空，则创建一个新的对象
 *
 *
 * 这种方式看上去是没有什么线程安全的问题，但是由于编译器的指令重排，
 * 再加上对象的初始化并非是原子的，所以可能会出现一种情况（获取的单例对象是没有初始化的）
 *
 * 对象的创建分为以下三步：
    1 memory=allocate();// 分配内存 相当于c的malloc
    2 ctorInstanc(memory) //初始化对象
    3 instance=memory //设置s指向刚分配的地址 （这个时候instance就已经不是null 了）
 *
 * 编译器运行时，可能会出现重排序 从1-2-3 排序为1-3-2
 *
 * 这样的话就有可能会出现一种情况，当线程A 运行到singleTon4=new SingleTon4(); 时，并先执行了创建对象的 1和3 步骤
 * 这个时候线程B进行第一判断singleTon4==null， 判断不是null 直接返回，这个时候返回的对象是没有经过初始化的
 */
public class SingleTon6 {
    private static SingleTon6 singleTon4;
    private SingleTon6(){

    }
    public static SingleTon6 getInstance(){
        if (singleTon4==null){
            synchronized (SingleTon6.class){
                if (singleTon4==null){
                    singleTon4=new SingleTon6();
                }
            }
        }
        return singleTon4;
    }
}
